1var Hatena = Hatena || {}; 2 3/* UTF-8 ã§ãªããã¼ã¸ããèªã¿è¾¼ã¾ãã¦ãåãããã«ã 4 * ã³ã¡ã³ãã¯è¤æ°è¡ã³ã¡ã³ã (éãã "*" ã®åã«ã¹ãã¼ã¹ãç½®ã) ã使ãã 5 * æååãªãã©ã«ä¸ã® ASCII å¤ã®æå㯠\uXXXX ã¨ã¨ã¹ã±ã¼ãããã 6 */ 7 8(function (Hatena) { 9 10var B = Hatena.Bookmark = Hatena.Bookmark || {}; 11if (B.BookmarkButton) return; 12 13if (location.protocol === 'https:') { 14 B.apiOrigin = 'https://b.hatena.ne.jp'; 15} else { 16 B.apiOrigin = 'http://cdn.api.b.hatena.ne.jp'; 17} 18B.origin = location.protocol + 'http://b.hatena.ne.jp'; 19B.staticOrigin = location.protocol + 'http://b.st-hatena.com'; 20 21var match = new RegExp('^((?:local|b(?!log)\\w+)\\.hatena\\.ne\\.jp(?::3000)?)$').exec(location.host); 22var isLocal; 23if (match) { 24 B.origin = B.apiOrigin = B.staticOrigin = 'http://' + match[1]; 25 isLocal = true; 26} 27 28var U = B.ButtonUtils = {}; 29 30var extend = U.extend = function (dest, src) { 31 for (var i in src) 32 dest[i] = src[i]; 33 return dest; 34}; 35 36var E = U.createElement = function (name, props) { 37 var element = document.createElement(name); 38 for (var p in props) 39 element[p] = props[p]; 40 for (var i = 2; i < arguments.length; i++) { 41 var child = arguments[i]; 42 if (!child.nodeType) 43 child = document.createTextNode(child); 44 element.appendChild(child); 45 } 46 return element; 47}; 48 49var getLocation = U.getLocation = function () { 50 var url = location.href; 51 /* Safari 㯠location.href ã§ãã¹ä¸ã® URI ã¨ã¹ã±ã¼ãã 52 * ãã³ã¼ããã¦ãã¾ãã®ã§ãdocument.URL ã調ã¹ã¦ã¿ã 53 */ 54 if (url.length < document.URL.length) 55 url = document.URL; 56 return url; 57}; 58 59var View = U.View = { 60 root: null, 61 clientLeft: 0, 62 clientTop: 0, 63 init: function () { 64 this.root = ((document.compatMode || '') === 'CSS1Compat') 65 ? document.documentElement : document.body; 66 this.clientLeft = this.root.clientLeft || 0; 67 this.clientTop = this.root.clientTop || 0; 68 }, 69 getElementRect: function (element) { 70 if (!this.root) this.init(); 71 this.getElementRect = element.getBoundingClientRect 72 ? this.getElementRectByRect : this.getElementRectByOffset; 73 return this.getElementRect(element); 74 }, 75 getElementRectByRect: function (element) { 76 var rect = element.getBoundingClientRect(); 77 var scroll = this.getScroll(); 78 return { 79 x: rect.left + scroll.x - this.clientLeft, 80 y: rect.top + scroll.y - this.clientTop, 81 width: rect.width || rect.right - rect.left, 82 height: rect.height || rect.bottom - rect.top 83 }; 84 }, 85 getElementRectByOffset: function (element) { 86 var x = 0, y = 0; 87 for (var node = element, base; base = node.offsetParent; node = base) { 88 x += node.offsetLeft; 89 y += node.offsetTop; 90 } 91 return { x: x, y: y, width: element.offsetWidth, height: element.offsetHeight }; 92 }, 93 getWindowSize: function () { 94 if (!this.root) this.init(); 95 return { width: this.root.clientWidth, height: this.root.clientHeight }; 96 }, 97 getDocumentSize: function () { 98 if (!this.root) this.init(); 99 return { width: this.root.scrollWidth, height: this.root.scrollHeight }; 100 }, 101 getScroll: function () { 102 if (!this.root) this.init();
103 this.getScroll = (typeof window.pageXOffset === 'number') 104 ? this.getScrollByPage : this.getScrollByRoot; 105 return this.getScroll(); 106 }, 107 getScrollByPage: function () { 108 return { x: window.pageXOffset, y: window.pageYOffset }; 109 }, 110 getScrollByRoot: function () { 111 return { x: this.root.scrollLeft, y: this.root.scrollTop }; 112 } 113}; 114 115var Dispatchable = U.Dispatchable = { 116 addEventListener: function (type, listener) { 117 var listeners = this.getListeners(type); 118 for (var i = 0; i < listeners.length; i++) 119 if (listeners[i] === listener) 120 return; 121 listeners.push(listener); 122 }, 123 removeEventListener: function (type, listener) { 124 var listeners = this.getListeners(type); 125 for (var i = 0; i < listeners.length; i++) { 126 if (listeners[i] === listener) { 127 listeners.splice(i, 1); 128 return; 129 } 130 } 131 }, 132 dispatchEvent: function (type, data) { 133 var event = new Dispatchable.Event(type, data); 134 var listeners = this.getListeners(type); 135 for (var i = 0; i < listeners.length; i++) 136 listeners[i].call(this, event); 137 return !event.defaultPrevented; 138 }, 139 getListeners: function (type) { 140 if (!this.hasOwnProperty('_listenersMap')) 141 this._listenersMap = {}; 142 return this._listenersMap[type] || (this._listenersMap[type] = []); 143 } 144}; 145 146Dispatchable.Event = function (type, data) { 147 this.type = type; 148 this.data = data; 149 this.defaultPrevented = false; 150}; 151 152extend(Dispatchable.Event.prototype, { 153 preventDefault: function () { 154 this.defaultPrevented = true; 155 } 156}); 157 158var Observer = U.Observer = function (target, type, handler, method) { 159 this.target = target; 160 this.type = type; 161 this.listener = handler; 162 if (method) { 163 this.listener = (typeof method === 'string') 164 ? function () { return handler[method].apply(handler, arguments); } 165 : function () { return handler.apply(method, arguments); }; 166 } 167 if (!target.addEventListener && target.attachEvent) { 168 var listener = this.listener; 169 this.listener = function (event) { 170 return listener.call(target, Observer.WrappedEvent.create(event)); 171 }; 172 this.start = this.startAttach; 173 this.stop = this.stopAttach; 174 } 175 this.start(); 176}; 177 178extend(Observer.prototype, { 179 start: function () { 180 this.target.addEventListener(this.type, this.listener, false); 181 }, 182 stop: function () { 183 this.target.removeEventListener(this.type, this.listener, false); 184 }, 185 startAttach: function () { 186 this.target.attachEvent('on' + this.type, this.listener); 187 }, 188 stopAttach: function () { 189 this.target.detachEvent('on' + this.type, this.listener); 190 } 191}); 192 193Observer.WrappedEvent = { 194 create: function (event) { 195 /* ä¸é¨ã® IE8 ã§ã®ã¯ã©ãã·ã¥å¯¾ç 196 * cf: http://vividcode.hatenablog.com/entry/ie/ie8_posmes_crash */ 197 if ( event.type === "message" ) { 198 return event; 199 } 200 var e = document.createEventObject(event); 201 e._event = event; 202 e.target = event.srcElement; 203 var scroll = View.getScroll(); 204 e.pageX = event.clientX + scroll.x - View.clientLeft; 205 e.pageY = event.clientY + scroll.y - View.clientTop; 206 e.stopPropagation = this.stopPropagation; 207 e.preventDefault = this.preventDefault; 208 return e; 209 }, 210 stopPropagation: function () { 211 this._event.cancelBubble = true; 212 }, 213 preventDefault: function () { 214 this._event.returnValue = false; 215 } 216}; 217 218var JSON = U.JSON = window.JSON || { 219 _tokenRE: /[{}\[\],:]|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b|\"(?:[^\u0000-\u001f\"\\]|\\(?:[\"\\\/bfnrt]|u[0-9A-Fa-f]{4}))*\"|\b(?:true|false|null)\b|\s+/g, 220 _escapeChar: function (c) { 221 return '\\u' + (0x10000 + c.charCodeAt(0)).toString(16).substring(1); 222 }, 223 224 parse: function (json) { 225 json = String(json); 226 if (json.replace(JSON._tokenRE, '') !== '') 227 throw new Error('Invalid JSON sytax'); 228 return eval('(' + json + ')'); 229 }, 230 stringify: function (value) { 231 switch (typeof value) { 232 case 'string': 233 return '"' + value.replace(/[\u0000-\u001f\"\\\u2028\u2029]/g, JSON._escapeChar) + '"'; 234 case 'number': 235 case 'boolean': 236 return '' + value; 237 case 'object': 238 if (!value) return 'null';
239 var stringify = JSON.stringify; 240 var type = Object.prototype.toString.call(value).slice(8, -1); 241 switch (type) { 242 case 'String': case 'Number': case 'Boolean': 243 return stringify(value.valueOf()); 244 case 'Array': 245 var members = []; 246 for (var i = 0; i < value.length; i++) 247 members.push(stringify(value[i])); 248 return '[' + members.join(',') + ']'; 249 case 'Object': 250 var members = []; 251 for (var i in value) 252 if (value.hasOwnProperty(i)) 253 members.push(stringify(i) + ':' + stringify(value[i])); 254 return '{' + members.join(',') + '}'; 255 } 256 return 'null'; 257 } 258 return 'null'; 259 } 260}; 261 262var WindowMessenger = U.WindowMessenger = function (win, url) { 263 this.win = win; 264 this.origin = url.replace(/^(https?:\/\/[^\/?#]+)[\s\S]*/, '$1'); 265 this.observer = new Observer(window, 'message', this, 'messageHandler'); 266}; 267 268extend(WindowMessenger, { 269 usePostMessage: true, 270 keySeed: (Math.random() * 0x10000) << 8, 271 createForFrame: function (frame, url) { 272 var win = frame.contentWindow; 273 /* WebKit ã§ã¯ãã¬ã¼ã ãã¨ã«å¥ã®ååãã¤ããå¿ è¦ãã */ 274 win.name = (++this.keySeed).toString(36) + '|' + getLocation(); 275 win.location.replace(url); 276 return new this(win, url); 277 } 278}); 279 280extend(WindowMessenger.prototype, Dispatchable); 281extend(WindowMessenger.prototype, { 282 send: function (type, data) { 283 if (typeof data === 'undefined') data = null; 284 var message = 'HBMessage@' + JSON.stringify({ type: type, data: data }); 285 this.win.postMessage(message, this.origin); 286 }, 287 messageHandler: function (event) { 288 var origin = event.origin || event.uri.replace(/^(https?:\/\/[^\/?#]+)[\s\S]*/, '$1'); 289 if (origin !== this.origin || event.source != this.win || 290 !/^HBMessage@/.test(event.data)) return; 291 var message = JSON.parse(event.data.substring(10)); 292 this.dispatchEvent(message.type, message.data); 293 }, 294 destroy: function () { 295 this.observer.stop(); 296 } 297}); 298 299if (!window.postMessage) { 300 301WindowMessenger = U.WindowMessenger = function (win, url, key) { 302 this.win = win; 303 this.url = url.replace(/#[\s\S]*/, ''); 304 this.key = key; 305 WindowMessenger.instances[this.key] = this; 306 if (!WindowMessenger.timerId) WindowMessenger.init(); 307}; 308 309extend(WindowMessenger, { 310 usePostMessage: false, 311 instances: {}, 312 interval: 20, 313 timerId: 0, 314 createForFrame: function (frame, url) { 315 var win = frame.contentWindow; 316 var key = this.makeFNVHash(url + '|' + Math.random()).toString(36); 317 win.name = key + '|' + getLocation(); 318 win.location.replace(url); 319 return new this(win, url, key); 320 }, 321 /* http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function */ 322 makeFNVHash: function (string) { 323 var hash = 2166136261; 324 for (var i = 0; i < string.length; i++) 325 hash = ((hash * 16777619) ^ string.charCodeAt(i)) >>> 0; 326 return hash; 327 }, 328 init: function () { 329 this.lastFragment = location.hash; 330 var WM = this; 331 this.timerId = window.setInterval(function () { WM.observe(); }, this.interval); 332 }, 333 observe: function () { 334 var fragment = location.hash; 335 if (fragment === this.lastFragment) return; 336 var match = fragment.match(/^#HBMessage-(\w+)-([^\/]+)\/(.+)
336/); 337 if (!match) { 338 this.lastFragment = fragment; 339 return; 340 } 341 /* "#" ã ã¨ãã¼ã¸æä¸é¨ã¸ã®ã¹ã¯ãã¼ã«ãçºçããã®ã§ "#_" ã§ */ 342 this.lastFragment = this.lastFragment || '#_'; 343 var scroll = View.getScroll(); 344 location.replace(this.lastFragment); 345 window.scrollTo(scroll.x, scroll.y); 346 var messenger = this.instances[match[1]]; 347 if (!messenger) return; 348 var type = decodeURIComponent(match[2]); 349 var data = JSON.parse(decodeURIComponent(match[3])); 350 messenger.dispatchEvent(type, data); 351 } 352}); 353 354extend(WindowMessenger.prototype, Dispatchable); 355extend(WindowMessenger.prototype, { 356 send: function (type, data) { 357 if (typeof data === 'undefined') data = null; 358 var url = this.url + '#HBMessage-' + this.key + '-' + 359 encodeURIComponent(type) + '/' + 360 encodeURIComponent(JSON.stringify(data)); 361 try { 362 this.win.location.replace(url); 363 } catch (ex) { 364 this.win.location.href = url; 365 } 366 }, 367 destroy: function () { 368 delete WindowMessenger.instances[this.key]; 369 } 370}); 371 372} /* WindowMessenger implementation with fragment identifier */ 373 374B.BookmarkButton = function (link) { 375 this.url = link.getAttribute('data-hatena-bookmark-url') || 376 B.BookmarkButton.extractURL(link.href) || 377 B.BookmarkButton.getCurrentURL(); 378 this.link = link; 379 this.mode = B.BookmarkButton.isTouchBrowser 380 ? 'goto-touch' : this.link.getAttribute('data-hatena-bookmark-mode'); 381 /* IE 7 ã¯ããã©ã«ãã®ã»ãã¥ãªãã£è¨å®ã«ãããã¬ã¼ã å ã§ã®ããã«ã®åä½ã« 382 * æ¯éããããã®ã§ããã¬ã¼ã å ã§ã¯ãããã¢ãããéããã¨ãå¼·å¶ããã 383 */ 384 if (!WindowMessenger.usePostMessage && 385 /\bMSIE 7\b/.test(navigator.userAgent) && 386 window.self != window.top) { 387 this.mode = 'popup'; 388 } 389 this.setup(); 390}; 391 392extend(B.BookmarkButton, { 393 interval: 428, /* Welcome to Shibuya.js! */ 394 timerId: 0, 395 setup: function () { 396 if (this.timerId) return; 397 var Button = this; 398 this.timerId = window.setInterval(function () { Button.tryCreate(); }, this.interval); 399 this.tryCreate(); 400 }, 401 lastLinkCount: 0, 402 tryCreate: function () { 403 var links = document.getElementsByTagName('a'); 404 var linkCount = links.length; 405 if (linkCount === this.lastLinkCount) return; 406 var buttonLinks = []; 407 var classRE = /(?:^|\s)hatena-bookmark-button(?:\s|$)/; 408 for (var i = 0; i < linkCount; i++) 409 if (classRE.test(links[i].className) && 410 !links[i].getAttribute('data-hatena-bookmark-initialized')) 411 buttonLinks.push(links[i]); 412 for (var i = 0; i < buttonLinks.length; i++) 413 new B.BookmarkButton(buttonLinks[i]); 414 this.lastLinkCount = links.length; 415 }, 416 extractURL: function (entryURL) { 417 if (!entryURL) return null; 418 var match = entryURL.match(/^http:\/\/b\.hatena\.ne\.jp\/entry\/(?:add\/)?(.+)/); 419 if (!match) return null; 420 var url = match[1]; 421 var parts = url.match(/^(?:https?(?:(:)|(%3A))|(s\/))?/); 422 if (parts[2]) { 423 try { 424 return decodeURIComponent(url); 425 } catch (ex) { 426 return unescape(url); 427 } 428 } 429 if (!parts[1]) 430 url = parts[3] ? 'https://' + url.substring(2) : 'http://' + url; 431 return url.replace(/%23/g, '#'); 432 }, 433 getCurrentURL: function () { 434 var url = getLocation(); 435 var canonicalURL = this.getCanonicalURL(); 436 if (canonicalURL) { 437 var index = url.indexOf('#'); 438 if (index >= 0 && canonicalURL.indexOf('#') < 0) 439 canonicalURL += url.substring(index); 440 url = canonicalURL; 441 } 442 return url; 443 }, 444 getCanonicalURL: function () { 445 var links = document.getElementsByTagName('link'); 446 for (var i = 0; i < links.length; i++) { 447 if (links[i].rel.toLowerCase() !== 'canonical' || !links[i].href) continue; 448 /* IE ã§ href ããããã£ã絶対 URL ã«è§£æ±ºãããªããã¨ããã */ 449 var a = document.createElement('a'); 450 a.href = links[i].href; 451 return a.cloneNode(false).href; 452 } 453 return null; 454 }, 455 isTouchBrowser: /\b(?:iPhone|iPod);| Android /.test(navigator.userAgent), 456 forcedLayout: '' 457}); 458 459extend(B.BookmarkButton.prototype, { 460 setup: function () { 461 var layout = B.BookmarkButton.forcedLayout || this.link.getAttribute('data-hatena-bookmark-layout'); 462 if (layout === 'simple') { 463 this.link.setAttribute('data-hatena-bookmark-initialized', '1'); 464 this.observer = new Observer(this.link, 'click', this, 'clickHandler'); 465 this.button = this.link; 466 /* ãªã³ã¯ã®å 容ãç»åã²ã¨ã¤ã®ã¿ãªããã®ç»åãåºæºã«ããã«ã表示 */ 467 var images = this.link.getElementsByTagName('img'); 468 this.anchor = (images.length === 1) ? images[0] : this.link; 469 if (!isLocal && !/^https?:\/\/b\.hatena\.ne\.jp\/(?!articles(?![\w-]))/.test(getLocation())) { 470 this.image = new Image(); 471 this.image.src = B.apiOrigin + '/entry/button/?url=' + encodeURIComponent(this.url) + '&layout=simple&format=image'; 472 } 473 } else { 474 var config = { 475 vertical: { height: 50 }, 476 'simple-balloon' : { width: 70, height: 20 }, 477 'standard-balloon': { width: 130, height: 20 }, 478 'standard-noballoon': { width: 80, height: 20 }, 479 'vertical-balloon': { width: 80, height: 60 } 480 }; 481 var width = 50, height = 20; 482 if (config[layout]) { 483 width = config[layout]['width'] || width; 484 height = config[layout]['height'] || height; 485 } 486 this.frame = E('iframe', { className: 'hatena-bookmark-button-frame', title: this.link.title, frameBorder: 0, scrolling: 'no', allowTransparency: true, width: width, height: height, src:'javascript:false' }); 487 this.frame.style.cssText = 'width: ' + width + 'px; height: ' + height + 'px;'; 488 this.link.parentNode.replaceChild(this.frame, this.link); 489 490 var buttonURL = B.apiOrigin + '/entry/button/?url=' + encodeURIComponent(this.url); 491 if (layout && layout !== 'standard') 492 buttonURL += '&layout=' + encodeURIComponent(layout); 493 var lang = this.link.getAttribute('data-hatena-bookmark-lang'); 494 if (lang) 495 buttonURL += '&lang=' + encodeURIComponent(lang); 496 if (this.mode === 'popup') 497 buttonURL += '&mode=' + encodeURIComponent(this.mode); 498 this.messenger = WindowMessenger.createForFrame(this.frame, buttonURL); 499 this.observer = new Observer(this.messenger, 'click', this, 'clickHandler'); 500 this._resizeObserver = new Observer(this.messenger, "resize", this, "resizeMessageHandler"); 501 this.button = this.frame; 502 this.anchor = this.frame; 503 } 504 }, 505 getTitle: function () { 506 var title = this.link.getAttribute('data-hatena-bookmark-title'); 507 if (!title) { 508 title = this.link.getAttribute('data-hatena-bookmark-escaped-title'); 509 if (title) 510 try { title = decodeURIComponent(title); } catch (ex) {} 511 }
512 if (!title && this.url.replace(/#.*/, '') === getLocation().replace(/#.*/, '')) 513 title = document.title; 514 return title; 515 }, 516 togglePanel: function () { 517 if (!this.panel) 518 this.panel = new B.BookmarkPanel(this.url, this.getTitle()); 519 if (this.panel.isShown) { 520 this.panel.hide(); 521 } else { 522 var position = this.link.getAttribute('data-hatena-bookmark-position'); 523 var hideBg = this.link.getAttribute('data-hatena-bookmark-hide-bg'); 524 var hideBackground = !hideBg || hideBg.toLowerCase() !== 'false'; 525 this.panel.show(this.anchor, position, hideBackground); 526 } 527 }, 528 gotoTouchEntry: function () { 529 var entryURL = B.origin + '/entry.touch/'; 530 var urlMatch = this.url.match(/^http(s)?:\/\/([\s\S]*)$/); 531 if (urlMatch) 532 entryURL += (urlMatch[1] ? 's/' : '') + urlMatch[2]; 533 else 534 entryURL += this.url; 535 location.href = entryURL.replace(/#/g, '%23'); 536 }, 537 gotoTouchBookmarklet: function () { 538 var bookmarkletURL = B.origin + '/bookmarklet.touch?url=' + encodeURIComponent(this.url); 539 var title = this.getTitle(); 540 if (title) 541 bookmarkletURL += '&btitle=' + encodeURIComponent(title); 542 location.href = bookmarkletURL; 543 }, 544 clickHandler: function (event) { 545 if ((event.which || event.button || 0) > 1) return; 546 if (event.stopPropagation) event.stopPropagation(); 547 if (event.preventDefault) event.preventDefault(); 548 switch (this.mode) { 549 case 'popup': 550 B.BookmarkPanel.openPopup(this.url, this.getTitle()); 551 break; 552 case 'goto-touch': 553 this.gotoTouchEntry(); 554 break; 555 default: 556 this.togglePanel(); 557 } 558 }, 559 resizeMessageHandler: function (evt) { 560 var width = evt.data.width + ""; 561 var height = evt.data.height + ""; 562 if (/^\d+$/.test(width)) this.frame.style.width = width + "px"; 563 if (/^\d+$/.test(height)) this.frame.style.height = height + "px"; 564 }, 565 destroy: function () { 566 if (this.observer) this.observer.stop(); 567 if (this._resizeObserver) this._resizeObserver.stop(); 568 if (this.messenger) this.messenger.destroy(); 569 if (this.panel) this.panel.destroy(); 570 if (this.button && this.button.parentNode) 571 this.button.parentNode.removeChild(this.button); 572 } 573}); 574 575B.BookmarkPanel = function (url, title) { 576 this.url = url; 577 this.title = title || ''; 578 this.isShown = false; 579 this.width = 365; 580 this.height = 160; 581 this.fixedTo = 'top'; 582 this.hiddenFlashes = []; 583 this.clickObserver = new Observer(document, 'click', this, 'clickHandler'); 584 this.clickObserver.stop(); 585 this.observers = [this.clickObserver]; 586 this.setup(); 587}; 588 589extend(B.BookmarkPanel, { 590 currentPanel: null, 591 makePanelURL: function (url, title) { 592 var panelURL = B.origin + '/entry/panel/?url=' + encodeURIComponent(url); 593 if (title) 594 panelURL += '&btitle=' + encodeURIComponent(title); 595 return panelURL; 596 }, 597 openPopup: function (url, title) { 598 var panelURL = this.makePanelURL(url, title); 599 var win = window.open(panelURL, 'hatena_bookmark_panel_popup', 'width=365,height=220,menubar=no,toolbar=no,resizable=yes'); 600 }, 601 hasCommonStyle: false, 602 setupCommonStyle: function () { 603 if (this.hasCommonStyle) return; 604 this.hasCommonStyle = true; 605 var resetCSSDeclarations = 606 'margin: 0; padding: 0; border: none; ' + 607 'position: static; float: none; width: auto; height: auto; ' + 608 'line-height: 1; vertical-align: baseline; ' + 609 'color: #222; background: none; ' + 610 'font-style: normal; font-weight:normal; font-size: medium; ' + 611 'text-indent: 0; text-align: left; text-decoration: none; ' + 612 'letter-spacing: normal; word-spacing: normal; white-space: normal;'; 613 var resetCSSText = 614 '.hatena-bookmark-bookmark-panel, ' + 615 '.hatena-bookmark-bookmark-panel * ' + 616 '{' + resetCSSDeclarations + '}'; 617 try { 618 var style = document.createElement('style'); 619 style.type = 'text/css'; 620 style.appendChild(document.createTextNode(resetCSSText)); 621 document.getElementsByTagName('head')[0].appendChild(style); 622 } catch (ex) { 623 document.createStyleSheet().cssText = resetCSSText; 624 } 625 }, 626 needsRebase: null, 627 getBasePosition: function () { 628 if (this.needsRebase === null) { 629 var style = window.getComputedStyle 630 ? getComputedStyle(document.body, null) 631 : document.body.currentStyle; 632 this.needsRebase = !!style && style.position !== 'static'; 633 } 634 return this.needsRebase ? View.getElementRect(document.body) : { x: 0, y: 0 }; 635 } 636}); 637 638extend(B.BookmarkPanel.prototype, { 639 setup: function () { 640 /* var frameTitle = (this.title ? 'ã' + this.title + 'ã' : 'ãã®ã¨ã³ããªã¼') + 'ãã¯ã¦ãªããã¯ãã¼ã¯ã«è¿½å '; */ 641 var frameTitle = (this.title ? '\u300E' + this.title + '\u300F' : '\u3053\u306E\u30A8\u30F3\u30C8\u30EA\u30FC') + '\u3092\u306F\u3066\u306A\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF\u306B\u8FFD\u52A0'; 642 this.panel = E('div', { className: 'hatena-bookmark-bookmark-panel' }, 643 this.loading = E('div', null, E('span', null, 'Now Loading...')), 644 this.content = E('div', null, 645 this.frame = E('iframe', { title: frameTitle, scrolling: 'no', frameBorder: 0, allowTransparency: true, src: 'javascript:false' }) 646 ) 647 ); 648 this.setupStyle(); 649 document.body.appendChild(this.panel); 650 var panelURL = B.BookmarkPanel.makePanelURL(this.url, this.title); 651 this.messenger = WindowMessenger.createForFrame(this.frame, panelURL); 652 this.observers.push( 653 /* frame ããã®ã¡ãã»ã¼ã¸å信失ææã®ä
653¿éº */ 654 new Observer(this.frame, 'load', this, 'showContent'), 655 new Observer(this.messenger, 'ready', this, 'showContent'), 656 new Observer(this.messenger, 'resize', this, 'resizeMessageHandler') 657 ); 658 }, 659 setupStyle: function () { 660 B.BookmarkPanel.setupCommonStyle(); 661 var size = 'width: ' + this.width + 'px; height: ' + this.height + 'px;'; 662 this.panel.style.cssText = 'position: absolute; z-index: 10002; display: none; ' + size; 663 this.loading.style.cssText = 'background-color: #fff; border: 3px solid #2c6ebd; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; text-align: center; width: ' + (this.width - 6) + 'px; height: ' + (this.height - 6) + 'px;'; 664 this.loading.firstChild.style.cssText = 'background: url("' + B.staticOrigin + '/images/loading.gif") left center no-repeat; padding-left: 23px; font-size: 0.85em; position: relative; top: ' + (this.height / 2 - 10) + 'px;'; 665 this.content.style.cssText = 'display: none;'; 666 this.frame.style.cssText = 'display: block; ' + size; 667 }, 668 show: function (anchor, position, hideBackground) { 669 if (this.isShown) return; 670 if (B.BookmarkPanel.currentPanel) 671 B.BookmarkPanel.currentPanel.hide(); 672 if (anchor) 673 this.anchorTo(anchor, position); 674 this.panel.style.display = ''; 675 this.isShown = true; 676 this.clickObserver.start(); 677 if (hideBackground) 678 this.hideFlashes(); 679 B.BookmarkPanel.currentPanel = this; 680 if (!this.loading) 681 this.messenger.send('notifysize'); 682 }, 683 hideFlashes: function () { 684 var flashes = []; 685 var embeds = document.getElementsByTagName('embed'); 686 for (var i = 0, embed; embed = embeds[i]; i++) 687 if (embed.type === 'application/x-shockwave-flash') 688 flashes.push(embed); 689 var objects = document.getElementsByTagName('object'); 690 for (var i = 0, object; object = objects[i]; i++) 691 if (object.type === 'application/x-shockwave-flash' || 692 (object.classid || '').toLowerCase() === 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000') 693 flashes.push(object); 694 if (!flashes.length) return; 695 var panelRect = View.getElementRect(this.panel); 696 var left = panelRect.x; 697 var top = panelRect.y; 698 var right = panelRect.x + panelRect.width; 699 var bottom = panelRect.y + Math.max(panelRect.height, 300); 700 for (var i = 0, flash; flash = flashes[i]; i++) { 701 var rect = View.getElementRect(flash); 702 if (rect.x + rect.width < left || right < rect.x || 703 rect.y + rect.height < top || bottom < rect.y) 704 continue; 705 flash.style.visibility = 'hidden'; 706 this.hiddenFlashes.push(flash); 707 } 708 }, 709 showContent: function () { 710 if (!this.loading) return; 711 this.panel.removeChild(this.loading); 712 this.loading = null; 713 this.content.style.display = ''; 714 }, 715 hide: function () { 716 if (!this.isShown) return; 717 this.panel.style.display = 'none'; 718 this.isShown = false; 719 this.clickObserver.stop(); 720 for (var i = 0, flash; flash = this.hiddenFlashes[i]; i++) 721 flash.style.visibility = ''; 722 this.hiddenFlashes = []; 723 B.BookmarkPanel.currentPanel = null; 724 }, 725 resize: function (width, height) { 726 if (width > 0) { 727 this.panel.style.width = width + 'px'; 728 this.frame.style.width = width + 'px'; 729 this.width = width; 730 } 731 if (height > 0) { 732 if (this.fixedTo === 'bottom') 733 this.panel.style.top = parseFloat(this.panel.style.top) + this.height - height + 'px'; 734 this.panel.style.height = height + 'px'; 735 this.frame.style.height = height + 'px'; 736 this.height = height; 737 } 738 }, 739 anchorTo: function (anchor, position) { 740 var rect = View.getElementRect(anchor); 741 var isLeft = position && position.indexOf('left') >= 0; 742 var isTop = position && position.indexOf('top') >= 0; 743 if (!position) { 744 var size = View.getWindowSize(); 745 var scroll = View.getScroll(); 746 isLeft = (scroll.x + size.width) - rect.x < this.width && 747 (rect.x + rect.width) - scroll.x >= this.width; 748 var h = Math.max(this.height, 300); 749 isTop = (scroll.y + size.height) - (rect.y + rect.height) < h && 750 rect.y - scroll.y >= h; 751 } 752 var left = isLeft ? rect.x + rect.width - this.width : rect.x; 753 var top = isTop ? rect.y - this.height - 2 : rect.y + rect.height + 2; 754 var base = B.BookmarkPanel.getBasePosition(); 755 this.panel.style.left = (Math.max(left, 2) - base.x) + 'px'; 756 this.panel.style.top = (Math.max(top, 2) - base.y) + 'px'; 757 this.fixedTo = isTop ? 'bottom' : 'top'; 758 }, 759 clickHandler: function (event) { 760 for (var node = event.target; node; node = node.parentNode) 761 if (node === this.panel) 762 return; 763 this.hide(); 764 }, 765 resizeMessageHandler: function (event) { 766 this.resize(event.data.width || -1, event.data.height || -1); 767 }, 768 destroy: function () { 769 this.hide(); 770 for (var i = 0, observer; observer = this.observers[i]; i++) 771 observer.stop(); 772 this.messenger.destroy(); 773 if (this.panel.parentNode) 774 this.panel.parentNode.removeChild(this.panel); 775 } 776}); 777 778})(Hatena); 779 780Hatena.Bookmark.BookmarkButton.setup();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.