Getting prop('tagName') problems in jQuery

Dadan Perez picture Dadan Perez · Mar 22, 2013 · Viewed 7.6k times · Source

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!

Answer

jfriend00 picture jfriend00 · Mar 22, 2013

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.