3

Having a bit of trouble with some strange setups I encountered while working on a bookmarklet for work purposes. I need it to be able to find all the video embeds on a page and process the information to generate JSON code to be inserted in our gallery setup. Problem is I am unable to reliably get the information needed to process the data.

first I find all the divs on the page with the proper itemprop

items = $('div[itemprop=video]');

Then using $.each() I begin the processing

thumbnail = getThumb($(this).find('*[itemprop=thumbnailUrl]'));
filename =  getFilename($(this).find('*[itemprop=contentUrl]'));
filelocation = getFilelocation( $(this).find('*[itemprop=contentUrl]'));

I need to be able to get the thumbnailURL and contentURL for processing,

    function getFilename(gfn) {
        if(gfn.prop('tagName') == 'META') {
            gfname = gfn.prop('content');
        } else {
            gfname = gfn.attr('href');
        }
        x = gfname.lastIndexOf('/');
        gfname = gfname.substr(x+1);
        y = gfname.lastIndexOf('.');
        gfname = gfname.substr(0,y);
        return gfname;
    }

.prop('tagName') keeps returning undefined when the itemprops aren't in meta tags, Anyone have any ideas on how to get this bookmarklet running?

Bookmarklets and source code available here

Edit: Because it was mentioned I'll go ahead and dump the bookmarklet code here with the superfluous gifs stripped out

    <a href="javascript:(function(){
var jQueryIsReady = function(){  
        if($('#vid2json_container').length < 1)
        {
            container = $(document.createElement('div'));
            container.attr('id','vid2json_container');
            container.css('position','fixed');
            container.css('top','0');
            container.css('left','0');
            container.css('background-color','#222222');
            container.css('padding','2px');
            container.css('border-style','solid');
            container.css('border-width','1px');
            container.css('border-color','#000000');
            container.css('opacity','0.95');
            container.css('z-index','999997');
            container.css('width','500px');
            container.css('height',window.innerHeight);
            container.css('overflow-y','auto');
            container.css('overflow-x','hidden');
            container.hide();

            divider_01 = $(document.createElement('div'));
            divider_01.css('clear','both');

            logo = $(document.createElement('img'));
            logo.attr('src','http://www.cityofdev.com/apps/bookmarklet/vid2json.png');
            logo.css('float','left');

            close_button = $(document.createElement('img'));
            close_button.attr('src','http://www.cityofdev.com/apps/bookmarklet/close_button.jpg');
            close_button.css('float','right');
            close_button.bind('click',function(){
                $('#vid2json_container').hide(500,function(){ 
                    $(this).remove();
                });
            });

            output = $(document.createElement('div'));
            output.attr('id','vid2json_output');
            output.css('color','#ffffff');

            container.append(logo);
            container.append(close_button);
            container.append(divider_01);
            container.append(output);

            $('body').prepend(container.show(500)); 
        }

        destination = $('#vid2json_output');
        destination.html('');

        items = $('div[itemprop=video]');

        output = $(document.createElement('div'));
        output.css('display','block');
        output.css('padding','0 0 10px');

        if(items.length > 0)
        {
            $.each(items,function(index,el){
                title = $(this).find('*[itemprop=name]').attr('content');
                thumbnail = getThumb($(this).find('*[itemprop=thumbnailUrl]'));
                filename =  getFilename($(this).find('*[itemprop=contentUrl]'));
                filelocation = getFilelocation($(this).find('*[itemprop=contentUrl]'));
                description = $(this).find('*[itemprop=description]').attr('content');
                city = getCity();
                citylink = getCitylink();
                category = getCategory();
                categorylink = getCategorylink();
                duration = $(this).find('*[itemprop=duration]').attr('content');

                head = $(document.createElement('span'));
                head.html(title+' -> JSON<br />\n');
                head.css('display','block');
                head.css('font-weight','700');
                head.css('font-size','12px');

                textarea = $(document.createElement('textarea'));
                textarea.css('width','100%');
                textarea.css('height','300px');
                textarea.css('margin','0 0 20px');

                vCode = '';
                vCode += '      {\n';
                vCode += '          &quot;title&quot;: &quot;'+title+'&quot;,\n';
                vCode += '          &quot;thumbnail&quot;: &quot;'+thumbnail+'&quot;,\n';
                vCode += '          &quot;filename&quot;: &quot;'+filename+'&quot;,\n';
                vCode += '          &quot;filelocation&quot;: &quot;'+filelocation+'&quot;,\n';
                vCode += '          &quot;description&quot;: &quot;'+description+'&quot;,\n';
                vCode += '          &quot;city&quot;: &quot;'+city+'&quot;,\n';
                vCode += '          &quot;citylink&quot;: &quot;'+citylink+'&quot;,\n';
                vCode += '          &quot;category&quot;: &quot;'+category+'&quot;,\n';
                vCode += '          &quot;categorylink&quot;: &quot;'+categorylink+'&quot;,\n';
                vCode += '          &quot;duration&quot;: &quot;'+duration+'&quot;,\n';
                vCode += '          &quot;height&quot;: &quot;&quot;,\n';
                vCode += '          &quot;width&quot;: &quot;&quot;\n';
                vCode += '      }\n';

                textarea.val(vCode);

                output.append(head);
                output.append(textarea);
                destination.append(output);
            });
        }else{
            output.html('No Items Found');
            destination.html(output);
        }

        scrollToTop = $(document.createElement('div'));
        scrollToTop.html('Scroll To Top');
        scrollToTop.css('cursor','pointer');
        scrollToTop.bind('click',function(){
            $('#vid2json_container').animate({ scrollTop: 0 },1000);
        });

        footer = $(document.createElement('div'));
        footer.css('font-size','9px');
        footer.css('color','#555555');
        footer.css('padding','5px 0');
        footer.html('VID2JSON bookmarklet programmed by David A Perez');

        destination.append(scrollToTop);
        destination.append(footer);

    };      

    var checkJquery = function(){
        if(typeof jQuery == 'undefined')
        {
            script01 = document.createElement('SCRIPT');
            script01.src = 'http://code.jquery.com/jquery-1.9.1.min.js';
            script01.type = 'text/javascript';
            document.getElementsByTagName('head')[0].appendChild(script01);
        }else{
            clearTimeout(interval);
            jQueryIsReady();
        }
    };

    var interval = setInterval(checkJquery,100);


    function getCategorylink()
    {
        catl = location.href;
        return catl;
    }

    function getCategory()
    {
        cat = $('.cat-header, .category-header').find('span, h1').html();

        return cat.replace(/^( ){1,}|( ){1,}$/gi,'');
    }

    function getCitylink()
    {
        cl = location.href;
        x = cl.indexOf('/',8);
        return cl.substr(0,x);
    }

    function getCity()
    {
        c = $('title').html();
        x = c.lastIndexOf('-');
        c = c.substr(x+1);
        y = c.lastIndexOf(',');
        c = c.substr(0,y);

        return c.replace(/^( ){1,}|( ){1,}$/gi,'');
    }

    function getFilelocation(gfl)
    {
        if(gfl.is('meta'))
        {
            gflocation = gfl.prop('content');
        }else{
            gflocation = gfl.attr('href');
        }

        x = gflocation.lastIndexOf('/');
        gflocation = gflocation.replace(/www/gi,'ww');
        gflocation = gflocation.substr(0,x+1);
        gflocation = gflocation.replace(/[^\/]{1,}$/,'');
        return gflocation.replace(/[\/]{2,}$/,'\/');
    }

    function getFilename(gfn)
    {
        if(gfn.is('meta'))
        {
            gfname = gfn.prop('content');
        }else{
            gfname = gfn.attr('href');
        }
        x = gfname.lastIndexOf('/');
        gfname = gfname.substr(x+1);
        y = gfname.lastIndexOf('.');
        gfname = gfname.substr(0,y);
        return gfname;
    }

    function getThumb(gt)
    {
        alert(gt.is('meta'));
        if(gt.is('meta'))
        {
            gtname = gt.prop('content');
        }else{
            gtname = gt.attr('src');
        }
        num = gtname.lastIndexOf('/');
        return gtname.substr(num+1);
    }        
})();">vid2json</a>

This is supposed to be run as a bookmarklet so it can be used on any page on their site. It is executed manually after the webpage is loaded, loads up jQuery, and once that's ready it begins processing. The part that seems to be causing the issue is

    $(this).find('*itemprop=ITEMPROP');

it works fine when the itemprops are in the meta tags however in the case of

<td class="ad" colspan="2" bgcolor="#000000" style="border:solid #CCCCCC 1px;">
<div itemscope itemtype="http://schema.org/LocalBusiness" style="color:#222222; font-weight: bold; text-align: center; width:580px;">
    <div itemprop="video" itemscope itemtype="http://schema.org/VideoObject">
        <meta itemprop="name" content="P.C.C.S. Dryer Vent Cleaning" />
        <meta itemprop="duration" content="T1M20S" />
        <meta itemprop="description" content="Fort Worth, TX dryer vent cleaning service." />
        <meta itemprop="height" content="580" />
        <meta itemprop="width" content="326" />
        <a href="http://204.145.110.12/thecityoffortworth.com/videos/pccs-dryer-vent-cleaning.mp4" itemprop="contentURL" style="display:block;width:580px; height:326px; border:0px; margin-bottom:104px;" id="pccs">
        <img src="pccs-dryer-vent-cleaning.png" alt="P.C.C.S. Dryer Vent Cleaning" width="580" height="430" border="0" itemprop="thumbnailURL" />
        </a>
    </div>
    <a href="http://www.fortworthsweep.com" class="style5" target="_blank" rel="nofollow" itemprop="url" style="color:#ffffff">www.fortworthsweep.com</a>
</div>

it returns 0 items. I've tried .find('meta[itemprop=contentURL],a[itemprop=contentURL]') but that also returns 0 items. The holdup really does seem like it's the a tag, Any ideas?

Also I do apologize if I'm doing anything wrong, this is my first time posting to Stackoverflow and I'm mostly self-taught with Javascript and jQuery. I'm doing my best to learn what is possible and what I can do to help out. Thank you for your patience and help!

Dadan Perez
  • 31
  • 1
  • 4

3 Answers3

2

The general concept of .prop('tagName') works fine as you can see in this jsFiddle. The issue is more likely that your jQuery object is empty (e.g. the selector did not find anything). To see if that is your issue, check the .length property on the jQuery object.

Also, you don't show us the overall context for this code. If it is being executed before the page has been parsed, then that could be another reason why your jQuery object is empty.

Per the jQuery documentation for .prop():

It returns undefined for the value of a property that has not been set, or if the matched set has no elements.

Since the tagName property is always set, the more likely issue is that your jQuery object is empty.

In the linked page you supplied, I can't find a way to set a breakpoint in any of your code so I'm not even sure it's being called/executed. This seems to be caused by you putting large amounts of code into a javascript: link rather than just calling a function.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I didn't put the entire thing into my post because I was worried It would be too big of a text dump which is why I made them available if anyone wanted to see the full thing, sorry about that. It's supposed to run as a bookmarklet which I believe is mentioned, the purpose is so that it can be run on any of the pages on the site as we need them. Before it begins processing it checks for jQuery and loads it if not found. It seems to run/process fine until it gets to the point where it tried to find the items with the itemprops, if they're not in the meta tags it doesn't return anything – Dadan Perez Mar 22 '13 at 15:50
0

jQuery has another way to test whether an element is a particular tag type, the .is() method:

if (gsn.is("meta"))

Not sure why the .prop call was giving undefined, unless gfn was empty.

MattW
  • 4,480
  • 1
  • 12
  • 11
  • Yes, gfn seems to return 0 results if it cannot find the itemprop it's looking for in the meta tags, I was hoping to find the right selector which would find the itemprop within the matched div regardless of what tag it was inside of but had no luck working it out myself. is('meta') does work and should help for checking if the element is a meta tag or not. Thanks for the help! – Dadan Perez Mar 22 '13 at 16:00
  • changed .find() to .children() since the itemprop thumbnailURL is inside of the but it doesn't seem to be finding that now – Dadan Perez Mar 22 '13 at 20:23
  • `.find()` would find the `` because it is a descendent of the `
    `, but `.children()` would not because it only scans immediate children, not all descendents.
    – MattW Mar 22 '13 at 21:18
0

Solution found!

It kind of took the long way around to force it to check everything, the selectors and .find() didn't seem to get the results I was looking for (possibly because of inconsistant caps) But i've managed to get it to work finally!

<a href="javascript:(function(){
var jQueryIsReady = function(){  
        if($('#vid2json_container').length < 1)
        {
            container = $(document.createElement('div'));
            container.attr('id','vid2json_container');
            container.css('position','fixed');
            container.css('top','0');
            container.css('left','0');
            container.css('background-color','#222222');
            container.css('padding','2px');
            container.css('border-style','solid');
            container.css('border-width','1px');
            container.css('border-color','#000000');
            container.css('opacity','0.95');
            container.css('z-index','999997');
            container.css('width','500px');
            container.css('height',window.innerHeight);
            container.css('overflow-y','auto');
            container.css('overflow-x','hidden');
            container.hide();

            divider_01 = $(document.createElement('div'));
            divider_01.css('clear','both');
            divider_02 = $(document.createElement('div'));
            divider_02.css('clear','both');

            logo = $(document.createElement('img'));
            logo.attr('src','http://www.cityofdev.com/apps/bookmarklet/vid2json.png');
            logo.css('float','left');

            close_button = $(document.createElement('img'));
            close_button.attr('src','http://www.cityofdev.com/apps/bookmarklet/close_button.jpg');
            close_button.css('float','right');
            close_button.bind('click',function(){
                $('#vid2json_container').hide(500,function(){ 
                    $(this).remove();
                });
            });

            nak = $(document.createElement('img'));
            nak.attr('id','naknak');
            nak.attr('src', 'http://www.cityofdev.com/apps/bookmarklet/naknak.gif');
            nak.css('float','left');
            nak.css('width','143px');
            nak.css('height','119px');
            nak.css('z-index','99998');

            salamander = $(document.createElement('img'));
            salamander.attr('id','salamander');
            salamander.attr('src', 'http://www.cityofdev.com/apps/bookmarklet/salamander.gif');
            salamander.css('float','right');
            salamander.css('width','112px');
            salamander.css('height','117px');
            salamander.css('z-index','99998');

            output = $(document.createElement('div'));
            output.attr('id','vid2json_output');
            output.css('color','#ffffff');

            container.append(logo);
            container.append(close_button);
            container.append(divider_01);
            container.append(nak);
            container.append(salamander);
            container.append(divider_02);
            container.append(output);

            $('body').prepend(container.show(500)); 
        }

        destination = $('#vid2json_output');
        destination.html('');

        items = $('div[itemprop=video]');

        output = $(document.createElement('div'));
        output.css('display','block');
        output.css('padding','0 0 10px');

        if(items.length > 0)
        {
            $.each(items,function(index,el){
                children = $(el).find('*');
                $.each(children, function(i,ele){
                    n = $(ele);
                    if(n.attr('itemprop') !== undefined)
                    {
                        switch(n.attr('itemprop').toLowerCase())
                        {
                            case 'name':
                                title = n.attr('content');
                            break;

                            case 'contenturl':
                                filename = getFilename(n);
                                filelocation = getFilelocation(n);
                            break;

                            case 'thumbnailurl':
                                thumbnail = getThumb(n);
                            break;

                            case 'description':
                                description = n.attr('content');
                            break;

                            case 'duration':
                                duration = n.attr('content');
                            break;
                            default:
                            break;
                        }                        
                    }

                });
                city = getCity();
                citylink = getCitylink();
                category = getCategory();
                categorylink = getCategorylink();

                head = $(document.createElement('span'));
                head.html(title+' -> JSON<br />\n');
                head.css('display','block');
                head.css('font-weight','700');
                head.css('font-size','12px');

                textarea = $(document.createElement('textarea'));
                textarea.css('width','100%');
                textarea.css('height','300px');
                textarea.css('margin','0 0 20px');

                vCode = '';
                vCode += '      {\n';
                vCode += '          &quot;title&quot;: &quot;'+title+'&quot;,\n';
                vCode += '          &quot;thumbnail&quot;: &quot;'+thumbnail+'&quot;,\n';
                vCode += '          &quot;filename&quot;: &quot;'+filename+'&quot;,\n';
                vCode += '          &quot;filelocation&quot;: &quot;'+filelocation+'&quot;,\n';
                vCode += '          &quot;description&quot;: &quot;'+description+'&quot;,\n';
                vCode += '          &quot;city&quot;: &quot;'+city+'&quot;,\n';
                vCode += '          &quot;citylink&quot;: &quot;'+citylink+'&quot;,\n';
                vCode += '          &quot;category&quot;: &quot;'+category+'&quot;,\n';
                vCode += '          &quot;categorylink&quot;: &quot;'+categorylink+'&quot;,\n';
                vCode += '          &quot;duration&quot;: &quot;'+duration+'&quot;,\n';
                vCode += '          &quot;height&quot;: &quot;&quot;,\n';
                vCode += '          &quot;width&quot;: &quot;&quot;\n';
                vCode += '      }\n';

                textarea.val(vCode);

                output.append(head);
                output.append(textarea);
                destination.append(output);
            });
        }else{
            output.html('No Items Found');
            destination.html(output);
        }

        scrollToTop = $(document.createElement('div'));
        scrollToTop.html('Scroll To Top');
        scrollToTop.css('cursor','pointer');
        scrollToTop.bind('click',function(){
            $('#vid2json_container').animate({ scrollTop: 0 },1000);
        });

        footer = $(document.createElement('div'));
        footer.css('font-size','9px');
        footer.css('color','#555555');
        footer.css('padding','5px 0');
        footer.html('VID2JSON bookmarklet programmed by David A Perez');

        destination.append(scrollToTop);
        destination.append(footer);

    };      

    var checkJquery = function(){
        if(typeof jQuery == 'undefined')
        {
            script01 = document.createElement('SCRIPT');
            script01.src = 'http://code.jquery.com/jquery-1.9.1.min.js';
            script01.type = 'text/javascript';
            document.getElementsByTagName('head')[0].appendChild(script01);
        }else{
            clearTimeout(interval);
            jQueryIsReady();
        }
    };

    var interval = setInterval(checkJquery,100);


    function getCategorylink()
    {
        catl = location.href;
        return catl;
    }

    function getCategory()
    {
        cat = $('.cat-header, .category-header').find('span, h1').html();

        return cat.replace(/^( ){1,}|( ){1,}$/gi,'');
    }

    function getCitylink()
    {
        cl = location.href;
        x = cl.indexOf('/',8);
        return cl.substr(0,x);
    }

    function getCity()
    {
        c = $('title').html();
        x = c.lastIndexOf('-');
        c = c.substr(x+1);
        y = c.lastIndexOf(',');
        c = c.substr(0,y);

        return c.replace(/^( ){1,}|( ){1,}$/gi,'');
    }

    function getFilelocation(gfl)
    {
        if(gfl.length<1){return 'contentURL not found'+gfl.length;}
        if(gfl.is('meta'))
        {
            gflocation = gfl.prop('content');
        }else{
            gflocation = gfl.attr('href');
        }

        x = gflocation.lastIndexOf('/');
        gflocation = gflocation.replace(/www/gi,'ww');
        gflocation = gflocation.substr(0,x+1);
        gflocation = gflocation.replace(/[^\/]{1,}$/,'');
        return gflocation.replace(/[\/]{2,}$/,'\/');
    }

    function getFilename(gfn)
    {
        if(gfn.length<1){return 'contentURL not found'+gfn.length;}
        if(gfn.is('meta'))
        {
            gfname = gfn.prop('content');
        }else{
            gfname = gfn.attr('href');
        }
        x = gfname.lastIndexOf('/');
        gfname = gfname.substr(x+1);
        y = gfname.lastIndexOf('.');
        gfname = gfname.substr(0,y);
        return gfname;
    }

    function getThumb(gt)
    {
        if(gt.length<1){return 'thumbnailURL not found'+gt.length;}
        if(gt.is('meta'))
        {
            gtname = gt.prop('content');
        }else{
            gtname = gt.attr('src');
        }
        num = gtname.lastIndexOf('/');
        return gtname.substr(num+1);
    }        
})();">vid2json</a>

The solution to the problem I was having

$.each(children, function(i,ele){
                    n = $(ele);
                    if(n.attr('itemprop') !== undefined)
                    {
                        switch(n.attr('itemprop').toLowerCase())
                        {
                            case 'name':
                                title = n.attr('content');
                            break;

                            case 'contenturl':
                                filename = getFilename(n);
                                filelocation = getFilelocation(n);
                            break;

                            case 'thumbnailurl':
                                thumbnail = getThumb(n);
                            break;

                            case 'description':
                                description = n.attr('content');
                            break;

                            case 'duration':
                                duration = n.attr('content');
                            break;
                            default:
                            break;
                        }                        
                    }
});

There are probably more efficient ways of getting through this but it seems to do the job reliably enough. I'll probably add more onto this as situations are encountered. Thanks for the advice guys, it helped me make my way to this solution!

Dadan Perez
  • 31
  • 1
  • 4