Using jQuery UI in a Bookmarklet

2019-04-12 22:36发布

In CoffeeScript, though this code is almost identical to JavaScript:

tabs_html = "<div id='nm-container'><ul><li><a href='#tabs-1'>Guidelines</a></li><li><a href='#tabs-2'>Test</a></li></ul>
            <div id='tabs-1'><p>something1</p></div><div id='tabs-2'><p>something2</p></div></div>"
$("#nm-toolbar").append(tabs_html)
$("#nm-container").tabs()

It doesn't work. Funny thing is it does work when trying the last line: $("#nm-container").tabs() from the console. I'm attaching the full code below. Note that I'm using CoffeeMarklet to generate the bookmarklet which seems to work only on chrome.

s1 = window.document.createElement('script')
s1.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'
window.document.body.appendChild(s1)

$ ->

    s2 = window.document.createElement('script')
    s2.src = 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js'
    window.document.body.appendChild(s2)

    jqueryUIcss = window.document.createElement('link')
    jqueryUIcss.rel = 'stylesheet'
    jqueryUIcss.type = 'text/css'
    jqueryUIcss.href = 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/themes/blitzer/jquery-ui.css'
    window.document.head.appendChild(jqueryUIcss)

    if $("#nm-toolbar").length == 0
        toolbar = "<div id='nm-toolbar'></div>"
        $("body").append(toolbar)
        $("#nm-toolbar").css({
            'background':               '#fafafa',
            'height':                   '500px',
            'width':                    '400px',
            'position':                 'fixed',
            'bottom':                   '0px',
            'right':                    '20px',
            'padding':                  '5px'
        })

        tabs_html = "<div id='nm-container'><ul><li><a href='#tabs-1'>Guidelines</a></li><li><a href='#tabs-2'>Test</a></li></ul>
            <div id='tabs-1'><p>something1</p></div><div id='tabs-2'><p>something2</p></div></div>"
        $("#nm-toolbar").append(tabs_html)
        $("#nm-container").tabs()

2条回答
可以哭但决不认输i
2楼-- · 2019-04-12 22:59

This should work:

((window, document, requirements, callback) ->
    getScript = (url, callback) ->
        script = document.createElement('script')
        script.src = url
        head = document.documentElement.childNodes[0]
        done = false
        script.onload = script.onreadystatechange = ->
          if not done and (not (readyState = @readyState) or readyState == 'loaded' or readyState == 'complete')
            done = true
            callback()
            script.onload = script.onreadystatechange = null
            head.removeChild script

        head.appendChild script

    if not ($ = window.jQuery) or requirements['jq'] > $.fn.jquery
        getScript 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.js', ->
            getScript 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.js', ->
                callback window.jQuery.noConflict(1)
    else
        if not (jqui_version = window.jQuery.ui.version) or requirements['jqui'] > jqui_version
            getScript 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.js', ->
                callback window.jQuery.noConflict(1)
        else
            callback window.jQuery.noConflict(1)

) window, document, {jq: '1.6.1', jqui: '1.8.7'}, ($) ->
    # Your code goes here:
    alert "jq: #{$.fn.jquery}, jqui: #{$.ui.version}"

You'd want to uncheck the "add jQuery" option on the CoffeeMarklet page to if using the above code

Update: Added checking for presence of jQuery and jQuery UI so it isn't loaded unnecessarily.

Although it could be improved by checking to see if the correct version of jQuery is already present as Ben Almans code does.

Attribution:

Beygi gave a lovely snippet for loading javascript resources one after another.

查看更多
乱世女痞
3楼-- · 2019-04-12 23:14

I suspect that the problem is that you're loading jQuery UI asynchronously. The line

window.document.body.appendChild(s2)

starts loading jQuery UI, but your code continues before jQuery UI has necessarily been loaded. That would explain why the tabs() call in your code fails, but it succeeds when you do it from the console, after the script has had time to load.

You should be able to fix this by making the rest of your code run from the callback

s2.onreadystatechange = ->
  return unless @readyState is 'complete'
  # the rest of the code goes here

Edit: And for that matter, you really should do the same thing with s1, or else the $ -> call could fail. The fact that it's succeeding suggests that either you have jQuery cached in your browser, or the page already has jQuery on it. You should also use noConflict to avoid overwriting the page's existing jQuery version. The Run jQuery Code Bookmarklet that Acorn linked to does all of these things (and in a more cross-browser manner than the code in this answer).

查看更多
登录 后发表回答